function [Exp] = expCreateFunc(state)
%expCreateFunc creates an experiment structure containing all data and
%stimulus information in an array of structures
%INPUTS:  A state structure passed from the gui containing
%         dataFileNames, a cell array of dataFileNames passed from ExpMaker
%         stimFileNames, a cell array of stimFileNames passed from ExpMaker
%         channelNames, cell array of channel names
%         chsToSave, array of channels user wants in the Exp
%         downSampleChs is a list of channels user wants to downsample
%         downSampleFactors is a list of factors to downsample channels by
%
%OUTPUTS: Exp, a two dimensional array of structs of all trials indexed by
%         run number and trial number: Exp(runNumber, trialNumber)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%copyright (c) 2012  Matthew Caudill
%
%this program is free software: you can redistribute it and/or modify
%it under the terms of the gnu general public license as published by
%the free software foundation, either version 3 of the license, or
%at your option) any later version.
%
%this program is distributed in the hope that it will be useful,
%but without any warranty; without even the implied warranty of
%merchantability or fitness for a particular purpose.  see the
%gnu general public license for more details.
%
%you should have received a copy of the gnu general public license
%along with this program.  if not, see <http://www.gnu.org/licenses/>.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%TESTING INPUTS
% state.dataFileNames = {'MSC_2012-06-29_n1ffgrating_3.daq',...
%                        'MSC_2012-06-29_n1ffgrating_4.daq',...
%                        'MSC_2012-06-29_n1ffgrating_5.daq',...
%                        'MSC_2012-06-29_n1ffgrating_6.daq'};
% state.stimFileNames = {'MSC_2012-6-29_n1ffgrating_3_TrialsStruct',...
%                         'MSC_2012-6-29_n1ffgrating_4_TrialsStruct',...
%                         'MSC_2012-6-29_n1ffgrating_5_TrialsStruct',...
%                         'MSC_2012-6-29_n1ffgrating_6_TrialsStruct'};
% state.chsToSave = [2 5];
% state.channelNames ={'Trigger','Voltage','Photodiode','Field','Encoder'};
% state.filterChs=[2];
% state.filter = 'Elliptic';
% state.order = 5;
% state.stopBandRipple = 40;
% state.passBandRipple = 3;
% state.type = 'high';
% state.cutOffFreq = 300;
% state.threshold = -8;
% state.maxSpikeWidth = 3;
% state.refractoryPeriod = 10;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Explanantion: Our goal is to combine the .daq data files with the
% stimulus trials structures generated by the visual stimulation PC and
% passed over to the DAQ PC. To do this, we will open each DAQ file and
% create a structure from the data called dataStruct. This structure will
% be combined with the trialsStruct into a super strucutre called EXP. Note
% in order to speed up the process of saving many data files and stimulus
% files together, I have written this code to take advantage of matlab
% vectorization. Unfortunately this can make the code a little less clear:
% I will document heavily.

%%%%%%%%%%%%%%%%%%%%%% DIRECTORY INFORMATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
electroExpDirInformation
daqFileLoc = DirInfo.DaqFileLoc;
stimFileLoc = DirInfo.StimFileLoc;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% We are first going to construct fieldNames for the fields that we will
% create in the dataStruct. These fieldNames arrived here from the state
% structure passed from the ExpMaker gui.
fieldNames = {state.chNames{state.chsToSave}};
stimulusStruct = struct([]);
tic
% In order to 'vectorize' this code we will avoid as many for loops as 
% possible and rely on matrix manipulations. We must loop over the fileName 
for name=1:numel(state.dataFileNames)
    
    %%%%%%%%%%%%%%%%%%%%%%%%%% GET DAQINFO %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %For each file we want to get a little ino about the file such as the
    %sampling rate etc so we can save these variables to EXP for later use.
    %We will use daqInfo function of the daq toolbox to accomplish this.
    daqinfo = daqread([daqFileLoc,state.dataFileNames{name}],'info');
    
    % number of triggers is stored in the following struct returned from
    % the above function daqinfo
    numTriggers = daqinfo.ObjInfo.TriggersExecuted;
    
    % we also want to include the sampling rate in the exp for later
    % reconstructing time series
    samplingFrequency = daqinfo.ObjInfo.SampleRate;
    samplesPerTrigg = daqinfo.ObjInfo.SamplesPerTrigger;
    
    Exp.fileInfo(name,1).samplingFreq = samplingFrequency;
    Exp.fileInfo(name,1).samplesPerTrigg = samplesPerTrigg;
    Exp.fileInfo(name,1).dataFileName = state.dataFileNames{name};
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    
    %%%%%%%%%%%%%%%%%%%%% LOAD STIMULUS TRIALS STRUCT %%%%%%%%%%%%%%%%%%%%%
    load([stimFileLoc,state.stimFileNames{name}])
    stimulusStruct = [stimulusStruct, trials];
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    
    %%%%%%%%%%%%%%%%%%%% READ IN DATA FILE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % Read data file
    data = daqread([daqFileLoc,state.dataFileNames{name}],...
                            'Channels', state.chsToSave);
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    
    %%%%%%%%%%%%%% BEGIN VECTORIZATION BY RESHAPE OF DATA %%%%%%%%%%%%%%%%%
    % Triggers are denoted by NaN's in the data so we remove these
    data(isnan(data(:,1)),:)=[]; 
    
    % We reshape the data to be a three dimensional array where rows are
    % data points, columns are triggers and 'depth' is chsToSave
    allData(:,:,:) = ...
                       reshape(data,[],numTriggers,numel(state.chsToSave));
    % We ultimatley want the data to be a stucture so we will first convert
    % into to a cell array using the row dimension as the length of each
    % array in the cell array.
    dataCell(:,:,:,name) = num2cell(allData,1);
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
end

%%%%%%%%%%%%%%%%%%%%%%%% PLACE DATA INTO EXP STRUCTURE %%%%%%%%%%%%%%%%%%%%
% our data is now stored in a cell array that is 1 x numTriggers x num
% chsToSave x numFiles so we are now ready to convert the cell array to a
% dataStruct. We will collapse the first dimension since it is no longer
% needed. The data structure will then by numTriggers x numFiles and will
% contain the fields specified by the third dimension in the cell array
% (i.e. the chsTo save.
dataStruct(:,:) = cell2struct(dataCell,fieldNames,3);

% Since it is more common to refernce the fileName first then the trigger
% number we transpose the whole structure
dataStruct = dataStruct';

% Add this structure to the Exp structure
Exp.data = dataStruct;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%% PLACE STIMULI INTO EXP STRUCTURE %%%%%%%%%%%%%%%%%%%%%
% Add the stimuli structure the the Exp struct
stimulusStruct = stimulusStruct';
Exp.stimulus = stimulusStruct;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%% FILTER & SPIKE DETECTION %%%%%%%%%%%%%%%%%%%%%%%%%%
% We will loop through files, triggers and chs to filter and call the
% IIR_filters with options passed from state, call the spikeDetection
% slgorithm and call the spikeEnvelope algorithm
for fileName = 1:size(dataStruct,1)
    for trigger = 1:size(dataStruct,2)
        for filterChIndex = 1:numel(state.filterChs)
            FiltSignal = IIR_Filter(...
                dataStruct(fileName,trigger).(state.chNames{...
                           state.filterChs(filterChIndex)}),...
                                        state.filter,...
                                        'order',state.order,...
                                        'cutOffFreq', state.cutOffFreq,...
                                        'passBandRipple',...
                                        state.passBandRipple,...
                                        'stopBandRipple',...
                                        state.stopBandRipple,...
                                        'type', state.type);
            spikeIndices{fileName,trigger,filterChIndex} = spikeDetect(...
                                   FiltSignal,...
                                   samplingFrequency,...
                                   state.threshold, state.maxSpikeWidth,...
                                   state.refractoryPeriod);
           spikeShapes{fileName,trigger,filterChIndex} = spikeEnvelope(...
                                  FiltSignal,...
                                  Exp.fileInfo(fileName,1).samplingFreq,...
                                  spikeIndices{fileName,trigger,...
                                  filterChIndex}, state.spikeWindow);
        end            
    end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%% PLACE SPIKE INDICES IN EXP STRUCTURE %%%%%%%%%%%%%%%%% 
% chs filtered
spikeFieldNames={state.chNames{state.filterChs}};
%construct spike indices struct
spikeIndicesStruct(:,:) = cell2struct(spikeIndices,spikeFieldNames,3);
%Add the spikeIndices struct to the Exp struct
Exp.spikeIndices = spikeIndicesStruct;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%% PLACE FILTER OPTIONS IN EXP STRUCTURE %%%%%%%%%%%%%%%%%%%%
% add the filter options that went in to making the spike indices struct
Exp.filterOptions.filterChs = state.filterChs;
Exp.filterOptions.filter = state.filter;
Exp.filterOptions.order = state.order;
Exp.filterOptions.cutoff = state.cutOffFreq;

if strcmp(state.filter,'Chebyshev_I')
    Exp.filterOptions.passBandRipple = state.passBandRipple;
end

if strcmp(state.filter,'Elliptic')
    Exp.filterOptions.passBandRipple = state.passBandRipple;
    Exp.filterOptions.stopBandRipple = state.stopBandRipple;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%% PLACE SPIKE DETECTION OPTIONS IN EXP STRUCTURE %%%%%%%%%%%%%%
% add all the spike detection options that went into detecting the spikes
% in the spike Indices struct
Exp.detectionOptions.detectOnChs = state.detectOnChs;
Exp.detectionOptions.spikeThreshold = state.threshold;
Exp.detectionOptions.maxSpikeWidth = state.maxSpikeWidth;
Exp.detectionOptions.refractoryPeriod = state.refractoryPeriod;
Exp.detectionOptions.spikeWindow = state.spikeWindow;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%% PLACE SPIKE SHAPES INTO EXP STRUCTURE %%%%%%%%%%%%%%%%%%%%
spikeShapeFieldNames={state.chNames{state.filterChs}};
%construct spike shapes struct
spikeShapesStruct(:,:) = cell2struct(spikeShapes,spikeShapeFieldNames,3);
%Add the spike shapes struct to the Exp struct
Exp.spikeShapes = spikeShapesStruct;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%% PERFORM RUN DETECTION %%%%%%%%%%%%%%%%%%%%%%%%%%%
if state.behaviorCheck
    if sum(strcmp('Encoder', fields(Exp.data)))>0
        for name = 1:size(Exp.data,1)
            for trigger = 1:size(Exp.data,2)
                boolean{name,trigger} = runDetect(...
                        Exp.data(name,trigger).Encoder,...
                        state.encoderOffset,...
                        state.encoderThreshold, state.encoderPercentage);
            end
        end
        % convert cell array to structure
        booleanStruct(:,:) = cell2struct(boolean,'Running',3);
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

        %%%%%%%%%%%%%% ADD BEHAVIOR TO EXP STRUCTURE %%%%%%%%%%%%%%%%%%%%%
        Exp.behavior = booleanStruct;
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    end
end

%assignin('base','Exp',Exp)
toc
